#include<stdio.h>
#include<stdlib.h>
#include "boolean.h"
#include "ADT_Infotype.h"

#ifndef ADT_DATABASE
#define ADT_DATABASE
// ADT DatabaseSosNet
// Menggunakan list to user address untuk merepresentasikan graf

typedef struct tMemberSosNet * address1;
typedef struct tFriendSosNet * address2;
typedef struct tMemberSosNet {
	infotype info;
	address2 teman;
	address1 next;
} MemberSosNet;
typedef struct tFriendSosNet {
	address1 info;
	address2 next;
} FriendSosNet;
typedef struct {
	address1 first;
} ListMember;

// {*****SELEKTOR*****}
#define First(L) (L).first
#define InfoMember(X) (X)->info
#define TemanMember(X) (X)->teman
#define NextMember(X) (X)->next
// X adalah pointer to MemberSosNet
#define InfoFriend(Y) (Y)->info
#define NextFriend(Y) (Y)->next
// Y adalah pointer to MemberSosNet
#define Nil NULL

// {*****MEMORY MANAGEMENT*****}
address1 Alokasi(infotype X);
// { Mengirimkan address hasil alokasi sebuah elemen }
// { Jika alokasi berhasil, maka address tidak Nil, dan misalnya menghasilkan P, maka
// Info(P) = X, Next(P) = Nil }
// { Jika alokasi gagal, mengirimkan Nil }
void Dealokasi(address1 * P);
// { I.S. P terdefinisi }
// { F.S. P dikembalikan ke sistem }
// { Melakukan dealokasi/pengembalian address P }

// {*****PREDIKAT*****}
bool IsListEmpty(ListMember L);
// { Mengirim true jika list kosong }

// {*****LIST_TRAVERSAL*****}
address1 SearchByInfo(ListMember L, infotype X);
// {Mengembalikan address dengan infotype X pada L}
// {Jika tidak ada elemen dengan infotype X, maka mengembalikan Nil}
bool IsMember(ListMember L, infotype X);
// {Mengirim true jika elemen X terdapat pada L}
bool IsExist(ListMember L, address1 P);
// {Mengirim true jika address P adalah salah satu elemen list}
int NbElmt(ListMember L);
// {Mengirim jumlah elemen L}
void PrintInfo(ListMember L);
// { I.S. List mungkin kosong }
// { F.S. Jika list tidak kosong, }
// {      Semua info yg disimpan pada elemen list diprint }
// {      Jika list kosong, hanya menuliskan "list kosong" }

// { *** PENAMBAHAN ELEMEN *** }
void InsVFirst (ListMember * L, infotype X);
// { I.S. L mungkin kosong }
// { F.S. X ditambahkan sebagai elemen pertama L }
// { Proses : Melakukan alokasi sebuah elemen dan menambahkan elemen pertama dengan
// nilai X jika alokasi berhasil.
// Jika alokasi gagal: I.S.= F.S. }
void InsVLast (ListMember * L, infotype X);
// { I.S. L mungkin kosong }
// { F.S. X ditambahkan sebagai elemen terakhir L }
// { Proses : Melakukan alokasi sebuah elemen dan menambahkan elemen list di akhir :
// elemen terakhir yang baru bernilai X jika alokasi berhasil.
// Jika alokasi gagal: I.S.= F.S. }

// { *** PENGHAPUSAN ELEMEN *** }
void DelVFirst (ListMember * L, infotype * X);
// { I.S. List L tidak kosong }
// { F.S. Elemen pertama list dihapus : nilai info disimpan pada X }
// {      dan alamat elemen pertama di-dealokasi }
void DelVLast (ListMember * L, infotype * X);
// { I.S. list tidak kosong }
// { F.S. Elemen terakhir list dihapus : nilai info disimpan pada X }
// {      dan alamat elemen terakhir di-dealokasi }

// { *** PENAMBAHAN ELEMEN BERDASARKAN ALAMAT *** }
void InsertFirst (ListMember * L, address1 P);
// { I.S. Sembarang, P sudah dialokasi  }
// { F.S. Menambahkan elemen ber-address P sebagai elemen pertama }
void InsertAfter (ListMember * L, address1 P, address1 Prec);
// { I.S. Prec pastilah elemen list dan bukan elemen terakhir, }
// {      P sudah dialokasi  }
// { F.S. Insert P sebagai elemen sesudah elemen beralamat Prec }
void InsertLast (ListMember * L, address1 P);
// { I.S. Sembarang, P sudah dialokasi }
// { F.S. P ditambahkan sebagai elemen terakhir yang baru }

// { *** PENGHAPUSAN SEBUAH ELEMEN *** }
void DelFirst (ListMember * L, address1 * P);
// { I.S. List tidak kosong }
// { F.S. P adalah alamat elemen pertama list sebelum penghapusan }
// {      Elemen list berkurang satu (mungkin menjadi kosong) }
// { First element yang baru adalah suksesor elemen pertama yang lama }
void DelP (ListMember * L, infotype X);
// { I.S. Sembarang }
// { F.S. Jika ada elemen list beraddress P, dengan Info(P) = X }
// { Maka P dihapus dari list dan di-dealokasi }
// { Jika tidak ada elemen list dengan Info(P) = X, maka list tetap }
// { List mungkin menjadi kosong karena penghapusan }
void DelLast (ListMember * L, address1 * P);
// { I.S. List tidak kosong }
// { F.S. P adalah alamat elemen terakhir list sebelum penghapusan  }
// {      Elemen list berkurang satu (mungkin menjadi kosong) }
// { Last element baru adalah predesesor elemen pertama yang lama, jika ada }
void DelAfter (ListMember * L, address1 * Pdel, address1 Prec);
// { I.S. List tidak kosong. Prec adalah anggota list L. }
// { F.S. Menghapus Next(Prec) : Pdel adalah alamat elemen list yang dihapus }

// {*****PENAMBAHAN ELEMEN - SPECIAL*****}
void InsertVTerurut (ListMember * L, infotype X);
// { I.S. L mungkin kosong, L adalah list terurut }
// { F.S. X ditambahkan sebagai elemen L dengan menjaga keterurutan L }
// { Proses : Melakukan alokasi sebuah elemen dan mencari tempat yang tepat untuk diinsert }
// { MEnggunakan fungsi IsLess dan IsMore pada ADT_Infotype}
// Jika alokasi gagal: I.S.= F.S. }
void InsertTerurut (ListMember * L, address1 P);
// { I.S. L mungkin kosong, L adalah list terurut, P sudah dialokasi }
// { F.S. Menambahkan elemen ber-address P sebagai elemen L dengan menjaga keterurutan list }

// {***************PEMPROSESAN ELEMEN LIST OF LIST (FRIEND) ***************}
// {*****MEMORY_MANAGEMENT*****}
address2 AlokasiFriend(address1 X);
// { Mengirimkan address hasil alokasi sebuah elemen }
// { Jika alokasi berhasil, maka address tidak Nil, dan misalnya menghasilkan P, maka
// Info(P) = X, Next(P) = Nil }
// { Jika alokasi gagal, mengirimkan Nil }
void DealokasiFriend(address2 * P);
// { I.S. P terdefinisi }
// { F.S. P dikembalikan ke sistem }
// { Melakukan dealokasi/pengembalian address P }

// {*****TRAVERSAL LIST OF LIST*****}
int NBFriend(address1 LL);
// {Mengembalikan jumlah friend dari elemen dengan address P}
bool IsFriend(address1 LL, address1 X);
// {Mengembalikan true jika X adalah friend dari LL}

// {*****PENAMBAHAN FRIEND*****}
void InsertVFriend(address1 LL, address1 X);
// { I.S. Sembarang }
// { F.S. X ditambahkan sebagai elemen terakhir yang baru }
// Jika alokasi gagal: I.S.= F.S.
void InsertFriend(address1 LL, address2 P);
// { I.S. Sembarang, P sudah dialokasi }
// { F.S. P ditambahkan sebagai elemen terakhir yang baru }

void DelVFriend(address1 LL, address1 X);
// { I.S. Sembarang }
// { F.S. X terhapus dari LL, apabila X adalah friend dari SS 
// Jika X bukan merupakan friend dari SS maka I.S = F.S }
void DeleteFriend(address1 LL, address2 P);
// {Prekondisi: address P pasti merupakan bagian dari list friend LL}

// {***** TAMBAHAN *****}
address1 SearchByEmail(ListMember L, char X[100]);
// {Mengembalikan address dengan email X pada L}
// {Jika tidak ada elemen dengan email X, maka mengembalikan Nil}
void DelElmt(ListMember * L, address1 X);
// {I.S. : Bukan list kosong}
// {F.S. : ListMember L dengan terhapus elemen beralamat X}

#endif

